#include "sock.h"
#include "epoll.h"
#include <unistd.h>

const uint16_t defaultPort = 8080;
const int num = 256;

class Epollserver
{
public:
    Epollserver(int port = defaultPort) : _port(port)
    {
        _listenfd.Socket();
        int opt = 1;
        setsockopt(_listenfd.Fd(), SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt));
        _listenfd.Bind(_port);
        _listenfd.Listen();
    }
    void Accepter()
    {
        int fd = _listenfd.Accept();
        _epoll.ctl(EPOLL_CTL_ADD, fd, EVENTIN);
    }
    void Recver(int fd)
    {
        char buffer[1024];
        ssize_t n = read(fd, buffer, sizeof(buffer) - 1);
        if(n > 0)
        {
            buffer[n] = 0;
            std::string messages = "server say# ";
            messages += buffer;
            std::cout << messages << std::endl;

            write(fd, messages.c_str(), messages.size());
        }
        else if(n == 0)
        {
            std::cout << "client close, close fd is : " << fd << std::endl;
            _epoll.ctl(EPOLL_CTL_DEL, fd, 0);
            close(fd);
        }
        else
        {
            std::cout << "read fail, close fd is : " << fd << std::endl;
            _epoll.ctl(EPOLL_CTL_DEL, fd, 0);
            close(fd);
        }

    }
    void Dispatcher(struct epoll_event events[], int size)
    {
        for(int i = 0; i < size; i++)
        {
            uint32_t event = events[i].events;
            int fd = events[i].data.fd;
            if(event & EPOLLIN)
            {
                if(fd == _listenfd.Fd())
                {
                    Accepter();
                }
                else
                {
                    Recver(fd);
                }
            }
            else if(event & EPOLLOUT)
            {

            }
            else
            {

            }
        }
    }
    void Start()
    {
        _epoll.ctl(EPOLL_CTL_ADD, _listenfd.Fd(), EVENTIN);
        struct epoll_event events[num];
        while(true)
        {
            int n = _epoll.wait(events, num);
            if(n > 0)
            {
                std::cout << "wait get!" << std::endl;
                Dispatcher(events, n);
            }
            else if(n == 0)
            {
                std::cout << "timeout..." << std::endl;
            }
            else
            {
                std::cout << "break..." << std::endl;
            }
        }
    }
private:
    Sock _listenfd;
    Epoll _epoll;
    uint16_t _port;
};